#coding=utf-8

import socket
import threading
from Queue import Queue


__author__ = 'Neo'


class App(object):

    def __init__(self, row, col, host, port):
        # 棋盘大小
        self.row = row
        self.col = col
        # 0代表没有放棋子，1和-1分别代码双方放的旗子
        self.chess = [[0 for i in range(col)] for j in range(row)]

        # 存放已经下好旗子的坐标,元祖方式, conn:[playerName, flag, set(), Queue]
        self.players = {}

        # 设置网络参数
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        print 'Socket has been created!'
        self.sock.bind((host, port))
        self.sock.listen(10)
        print 'Socket now listening'

        # # 设置thread
        # self.con = threading.Condition()
        # self.data = ''

        # # 存放socket与之对应Queue的map
        # self.msgQue = {}

        # 根据登陆的先后顺序随机分配黑白方
        self.flag = [1, -1]
        self.turn = None

    # # 显示通知消息
    # def notifyAll(self, info):
    #     # 将要显示的数据放入data中
    #     if self.con.acquire():
    #         self.data = info
    #         self.con.notifyAll()
    #         self.con.release()



    def check_win(self, pos):
        x, y = pos
        cnt, pinc, ninc = 1, 1, -1
        # 检查水平方向
        while pinc or ninc:
            if ninc and 0<=y+ninc and self.chess[x][y+ninc] == self.chess[x][y]:
                cnt += 1
                ninc -= 1
            else:
                ninc = 0
            if pinc and y+pinc<self.col and self.chess[x][y+pinc] == self.chess[x][y]:
                cnt += 1
                pinc += 1
            else:
                pinc = 0
        else:
            if cnt == 5:
                return True
            else:
                cnt, pinc, ninc = 1, 1, -1

        # 检查竖直方向
        while pinc or ninc:
            if ninc and 0<=x+ninc and self.chess[x+ninc][y] == self.chess[x][y]:
                cnt += 1
                ninc -= 1
            else:
                ninc = 0
            if pinc and x+pinc<self.row and self.chess[x+pinc][y] == self.chess[x][y]:
                cnt += 1
                pinc += 1
            else:
                pinc = 0
        else:
            if cnt == 5:
                return True
            else:
                cnt, pinc, ninc = 1, 1, -1
        # 检查主对角线方向
        while pinc or ninc:
            if ninc and 0<=x+ninc and 0<=y+ninc and self.chess[x+ninc][y+ninc] == self.chess[x][y]:
                cnt += 1
                ninc -= 1
            else:
                ninc = 0
            if pinc and x+pinc<self.row and y+pinc<self.col and self.chess[x+pinc][y+pinc] == self.chess[x][y]:
                cnt += 1
                pinc += 1
            else:
                pinc = 0
        else:
            if cnt == 5:
                return True
            else:
                cnt, pinc, ninc = 1, 1, -1

        # 检查副对角线方向
        while pinc or ninc:
            if ninc and 0<=x+ninc and y-ninc<self.col and self.chess[x+ninc][y-ninc] == self.chess[x][y]:
                cnt += 1
                ninc -= 1
            else:
                ninc = 0
            if pinc and x+pinc<self.col and 0<=y-pinc and self.chess[x+pinc][y-pinc] == self.chess[x][y]:
                cnt += 1
                pinc += 1
            else:
                pinc = 0
        else:
            if cnt == 5:
                return True
            else:
                cnt, pinc, ninc = 1, 1, -1

        return False

    def push_msg(self, msg):
        for c in self.players:
            self.players[c][3].put(msg, 1)


    def recv_data(self, conn):
        while True:
            try:
                temp = conn.recv(1024)
                # if not temp:
                #     conn.close()
                #     return

                # 接收到新的数据
                print temp
                cmd, data = temp.split('#')
                if 'login' == cmd:#首次登陆
                    # 初始化用户数据，旗子的颜色以及所放旗子的坐标
                    self.players[conn] = [data, self.flag.pop(), set(),  Queue(32)]
                    # 第一次登陆的先下棋
                    if None == self.turn:
                        self.turn = self.players[conn][1]
                    msg = 'login#' + str(self.players[conn][1])
                    self.players[conn][3].put(msg, 1)
                    if 2 == len(self.players):
                        msg = 'nick#'
                        lst = []
                        for c in self.players:
                            lst.append(self.players[c][0])
                            lst.append(str(self.players[c][1]))
                        msg += ','.join(lst)
                        self.push_msg(msg)
                        print msg
                elif 'logout' == cmd:
                    break
                elif 'pos' == cmd:
                    if self.turn == self.players[conn][1]:
                        self.turn = 1 if self.turn == -1 else -1
                        pos = tuple(map(int, data.split(',')))
                        self.players[conn][2].add(pos)
                        self.chess[pos[0]][pos[1]] = self.players[conn][1]
                        # check if someone has winned
                        # if self.check_win(pos):#胜利发送胜利方名字
                        #     msg = 'win#' + self.players[conn][0]
                        #     for c in self.players:
                        #         self.players[c][3].put(msg, 1)
                        # else:
                        msg = 'pos#' + str(self.players[conn][1]) + ',' + str(pos[0]) + ',' + str(pos[1])
                        # for c in self.players:
                        #     self.players[c][3].put(msg, 1)
                        self.push_msg(msg)
                        if self.check_win(pos):#胜利发送胜利方名字
                            msg = 'win#' + self.players[conn][0]
                            # for c in self.players:
                            #     self.players[c][3].put(msg, 1)
                            self.push_msg(msg)
            except:
                # return
                pass

    def send_data(self, conn):
        while True:
            try:
                data = self.players[conn][3].get(1)
                print data
                try:
                    conn.send(data)
                except:
                    pass
            except:
                pass


    def run(self):
        while True:
            # wait to accept a connection - blocking call
            conn, addr = self.sock.accept()
            print 'Connected with ' + addr[0] + ':' + str(addr[1])
            # nick = conn.recv(1024)
            # 新增玩家，创建数据
            # self.players[nick] = [flag.pop(), set()]


            # self.notifyAll('Welcome ' + nick + ' play the game!\n')
            # print self.data
            # print str((threading.activeCount() + 1) / 2) + ' person(s) now in the game!'
            # conn.send(str((threading.activeCount() + 1) / 2) + ' person(s) now in the game!')

            threading.Thread(target = self.recv_data , args = (conn,)).start()
            threading.Thread(target = self.send_data , args = (conn,)).start()

        self.sock.close()



if __name__ == '__main__':
    App(16, 16, '127.0.0.1', 30000).run()
